﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Desaware.MachineLicense40;
using System.Windows.Forms;
using System.Xml;
using WindowsFormsApp1;
using System.Configuration;

namespace FMS.Formulation.Licensing.Engine
{

    public class DesawareInterface
    {
        private const string RESOURCENAME = "Formulation";

        private static ClientLicense _theClientLicense = null;

        private static ClientSystemMatch _clientSystemMatch = new ClientSystemMatch();

        private static ISystemIdentifier[] _newIdentifiers = new ISystemIdentifier[4];

        private static string[] _activationServers;

        private int _serverTimeout = 300000;

        public int ServerTimeout => _serverTimeout;

        public DesawareInterface(int ServerTimeout)
        {
            string text = string.Empty;
            try
            {
                text = ConfigurationManager.AppSettings["ActivationURL"];
            }
            catch
            {
            }
            if (!string.IsNullOrEmpty(text))
            {
                _activationServers = new string[1] { text };
            }
            else
            {
                _activationServers = new string[1] { "http://brill.cql1215.top:9199/activator.asmx" };
            }
            if (ServerTimeout >= 30000)
            {
                _serverTimeout = ServerTimeout;
            }
        }

        internal ClientLicense GetDesawareClientLicense()
        {
            if (_theClientLicense == null)
            {
                _theClientLicense = new ClientLicense("Formulation");
                _theClientLicense.ServerTimeout = _serverTimeout;
                _theClientLicense.ExcludeDefaultSystemIdentifiers = true;
                _theClientLicense.LicenseServers = _activationServers;
                IWebProxy systemWebProxy = WebRequest.GetSystemWebProxy();
                if (systemWebProxy != null)
                {
                    Uri uri = new Uri(_activationServers[0]);
                    if (uri != null && !systemWebProxy.IsBypassed(uri))
                    {
                        _theClientLicense.Proxy = new WebProxy(systemWebProxy.GetProxy(uri));
                        if (_theClientLicense.Proxy != null)
                        {
                            _theClientLicense.Proxy.UseDefaultCredentials = true;
                        }
                    }
                }
                _theClientLicense.CustomData = null;
                _newIdentifiers[0] = new MachineIdentifiers();
                _newIdentifiers[1] = new BiosIdentifiers();
                _newIdentifiers[2] = new ProcessorIdentifiers();
                _newIdentifiers[3] = new NICIdentifiers();
                _theClientLicense.AdditionalSystemIdentifiers = _newIdentifiers;
                SystemMatch.RegisterMatchProcess(_theClientLicense.ApplicationName, _clientSystemMatch);
            }
            return _theClientLicense;
        }

        internal ClientLicense GetDesawareClientLicenseWithoutHardware()
        {
            ClientLicense clientLicense = new ClientLicense("Formulation");
            clientLicense.ServerTimeout = _serverTimeout;
            clientLicense.ExcludeDefaultSystemIdentifiers = true;
            clientLicense.LicenseServers = _activationServers;
            clientLicense.VerificationMode = VerificationModes.NoSystemVerification;
            IWebProxy systemWebProxy = WebRequest.GetSystemWebProxy();
            if (systemWebProxy != null)
            {
                Uri uri = new Uri(_activationServers[0]);
                if (uri != null && !systemWebProxy.IsBypassed(uri))
                {
                    clientLicense.Proxy = new WebProxy(systemWebProxy.GetProxy(uri));
                    if (clientLicense.Proxy != null)
                    {
                        clientLicense.Proxy.UseDefaultCredentials = true;
                    }
                }
            }
            clientLicense.CustomData = null;
            return clientLicense;
        }

        public string CheckLicense(string licenseLocation)
        {
            ClientLicense desawareClientLicense = GetDesawareClientLicense();
            desawareClientLicense.DemoRequireInternet = false;
            desawareClientLicense.LicenseFilePath = licenseLocation;
            ValidationStatus validationStatus = desawareClientLicense.VerifyLicense(DeferredCheckInBackground: true);
            if (validationStatus == ValidationStatus.Success)
            {
                if (desawareClientLicense.Licensed)
                {
                    return string.Empty;
                }
                return Strings.CertificateNotLicensedError_Text;
            }
            return string.Format(Strings.CertificateError_Text, validationStatus.ToString());
        }

        public bool CheckLicenseWithoutHardware(XmlDocument theXMLLicense, out string ErrorMessage)
        {
            ClientLicense desawareClientLicenseWithoutHardware = GetDesawareClientLicenseWithoutHardware();
            ErrorMessage = string.Empty;
            desawareClientLicenseWithoutHardware.DemoRequireInternet = false;
            ValidationStatus validationStatus = desawareClientLicenseWithoutHardware.VerifyLicense(DeferredCheckInBackground: true, theXMLLicense);
            if (validationStatus == ValidationStatus.Success)
            {
                if (desawareClientLicenseWithoutHardware.Licensed)
                {
                    return true;
                }
                ErrorMessage = Strings.CertificateNotLicensedError_Text;
                return false;
            }
            ErrorMessage = string.Format(Strings.CertificateError_Text, validationStatus.ToString());
            return false;
        }

        public InstallClientLicenseResults InstallClientLicense(string activationCode, string licenseLocation, out string errorMessage, bool AllowDeferred, bool suppressMessages, ref bool codeReUseWarning)
        {
            codeReUseWarning = false;
            errorMessage = string.Empty;
            ClientLicense desawareClientLicense = GetDesawareClientLicense();
            desawareClientLicense.LicenseFilePath = licenseLocation;
            desawareClientLicense.DemoRequireInternet = false;
            if (File.Exists(licenseLocation))
            {
                try
                {
                    File.SetAttributes(licenseLocation, FileAttributes.Normal);
                }
                catch
                {
                }
            }
            WMIInfo wMIInfo = new WMIInfo();
            if (!wMIInfo.Read())
            {
                if (wMIInfo.ErrorMessage.Length > 0)
                {
                    errorMessage = wMIInfo.ErrorMessage;
                    return InstallClientLicenseResults.LicenseWasNotCreated;
                }
                errorMessage = Strings.WMIReadError_Text;
                return InstallClientLicenseResults.LicenseWasNotCreated;
            }
            string text = BackupLicenseFile(licenseLocation);
            StringDictionary wMIDictionary = wMIInfo.WMIDictionary;
            wMIDictionary.Add("ActivationCode", activationCode);
            desawareClientLicense.CustomData = wMIDictionary;
            InstallClientLicenseResults result = InstallClientLicenseResults.LicenseWasNotCreated;
            try
            {
                InstallErrorResults installErrorResults = ((!AllowDeferred) ? desawareClientLicense.InstallLicense(activationCode, InstallationModes.SyncActivationRequired) : desawareClientLicense.InstallLicense(activationCode, InstallationModes.SyncAllowDeferred));
                if (!suppressMessages && installErrorResults == InstallErrorResults.CodeReuseWarning && Environment.UserInteractive)
                {
                    string friendlyErrorMessage = GetFriendlyErrorMessage(installErrorResults);
                    MessageBox.Show(friendlyErrorMessage, Strings.ActivationStatus_Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                if (installErrorResults == InstallErrorResults.CodeReuseWarning)
                {
                    codeReUseWarning = true;
                    installErrorResults = InstallErrorResults.NoError;
                }
                if (installErrorResults != 0)
                {
                    if (AllowDeferred && installErrorResults == InstallErrorResults.NoLicenseServers)
                    {
                        if (File.Exists(licenseLocation))
                        {
                            result = InstallClientLicenseResults.DeferredLicenseHasBeenCreated;
                        }
                        else
                        {
                            errorMessage = GetFriendlyErrorMessage(installErrorResults);
                        }
                    }
                    else
                    {
                        errorMessage = GetFriendlyErrorMessage(installErrorResults);
                    }
                }
                else
                {
                    VerifyNewCertificate(licenseLocation, ref errorMessage);
                    if (errorMessage.Length < 1)
                    {
                        result = InstallClientLicenseResults.LicenseIsGood;
                    }
                }
            }
            catch (Exception ex)
            {
                errorMessage = ex.Message;
            }
            if (errorMessage.Length > 0)
            {
                ReplaceWithBackupFile(licenseLocation, text);
            }
            else
            {
                DeleteFile(text);
            }
            return result;
        }

        private string BackupLicenseFile(string licenseLocation)
        {
            if (File.Exists(licenseLocation))
            {
                string text = Path.ChangeExtension(licenseLocation, ".BAK");
                DeleteFile(text);
                File.Copy(licenseLocation, text, overwrite: true);
                return text;
            }
            return string.Empty;
        }

        private void DeleteFile(string fileToDelete)
        {
            try
            {
                if (File.Exists(fileToDelete))
                {
                    try
                    {
                        File.SetAttributes(fileToDelete, FileAttributes.Normal);
                    }
                    catch
                    {
                    }
                    File.Delete(fileToDelete);
                }
            }
            catch
            {
            }
        }

        private void ReplaceWithBackupFile(string licenseLocation, string backupFile)
        {
            if (File.Exists(backupFile))
            {
                DeleteFile(licenseLocation);
                File.Move(backupFile, licenseLocation);
            }
        }

        private void VerifyNewCertificate(string licenseLocation, ref string errorMessage)
        {
            ReadCertificate readCertificate = new ReadCertificate();
            FMS.Formulation.Licensing.License.License theLicense = new FMS.Formulation.Licensing.License.License();
            if (readCertificate.ReadLicenseCertificate(licenseLocation, theLicense, out var _, out var _))
            {
                if (readCertificate.ServerDataBad)
                {
                    bool flag = false;
                    errorMessage = Strings.NewLicenseIsBadError_Text + Environment.NewLine + readCertificate.ErrorMessage + Environment.NewLine;
                }
            }
            else
            {
                errorMessage = Strings.UnableToReadCertificateError_Text;
            }
        }

        private string GetFriendlyErrorMessage(InstallErrorResults results)
        {
            string empty = string.Empty;
            switch (results)
            {
                case InstallErrorResults.CodeReuseWarning:
                    empty = Strings.CodeReuseWarning1_Text + Environment.NewLine;
                    empty = empty + Strings.CodeReuseWarning2_Text + Environment.NewLine;
                    return empty + Strings.CodeReuseWarning3_Text;
                case InstallErrorResults.DeferServerError:
                    return Strings.DeferServerError_Text;
                case InstallErrorResults.AsyncRequestStarted:
                    return Strings.AsyncRequestStartedError_Text;
                case InstallErrorResults.NoLicenseServers:
                    empty = Strings.NoLicenseServersError1_Text + Environment.NewLine;
                    return empty + Strings.NoLicenseServersError2_Text;
                case InstallErrorResults.DemoInstallOnPrevRegisteredSystem:
                    return Strings.DemoInstallOnPrevRegisteredSystemError_Text;
                case InstallErrorResults.FatalError:
                    return Strings.FatalError_Text;
                case InstallErrorResults.CodeReuseBlocked:
                    empty = Strings.CodeReuseBlockedError1_Text + Environment.NewLine;
                    return empty + Strings.CodeReuseBlockedError2_Text;
                case InstallErrorResults.InvalidCertificate:
                    return Strings.InvalidCertificateError_Text;
                case InstallErrorResults.ServerError:
                    empty = Strings.ServerError1_Text + Environment.NewLine;
                    empty = empty + Strings.ServerError2_Text + Environment.NewLine;
                    return empty + Strings.ServerError3_Text;
                case InstallErrorResults.NoSuchApplication:
                    return Strings.NoSuchApplicationError_Text;
                case InstallErrorResults.DemoInstallOnRegisteredSystem:
                    return Strings.DemoInstallOnRegisteredSystemError_Text;
                case InstallErrorResults.DemoExpired:
                    return Strings.DemoExpiredError_Text;
                case InstallErrorResults.CertSaveError:
                    return Strings.CertSaveError_Text;
                case InstallErrorResults.NoOperationCalled:
                    return Strings.NoOperationCalledError_Text;
                default:
                    return string.Format(Strings.UnknownError_Text, results.ToString());
            }
        }
    }

}
